# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__docformat__ = 'restructuredtext en'

from .. import formlib as layout

LEFT, RIGHT = layout.LEFT, layout.RIGHT


class FreeCellLayout(layout.Layout):
    """
    static block (top):
        - reserves. (horz. holdcards ignored. Ncards if reserve_texts.)
          foundations. (horz SUIT * 2. max of 10 cols.)
        - rows. (_offset if playcards.)

    dynamic block (bottom): align LEFT or RIGHT side. default LEFT.
        - talon (corner). waste (if Game._waste_. wastecards ignored).

    :cvar func _offset: dict('ycards': value)
    """

    _offset = lambda self, cards: {'ycards': cards}
    _halign = lambda self, max_rows, piles: (max_rows - piles) * self.HXS

    def create(self, rows, ncols=None, playcards=18, bases=None,
               reserves=0, reserve_texts=False, texts=False, wastecards=0,
               align=RIGHT, **kw):
        l, s = self, self.s
        assert l.size.width == 0
        ncols = ncols or rows
        # set foundation base caps
        bases = bases if type(bases) in (list, tuple) else l.SUITS
        f_cols = min(10, (len(bases) / l.NDECKS) * min(2, l.NDECKS))
        f_rows = len(l._get_row_size(len(bases), f_cols))
        # set max piles for centering groups
        size = reserves + f_cols
        max_width = max(size * l.XS, ncols * l._get_stack_width(playcards))
        max_cols = max(size, ncols)
        if 'xcards' in l._offset(playcards):
            dx = (max_width - size * l.XS) / 2
        else:
            dx = l._halign(max_cols, size)
        dy = (f_rows - 1) * l.HYS
        l._set_horz_reserves(x=l.XM + dx, y=l.YM + dy, reserves=reserves,
                             reserve_texts=reserve_texts, anchor='s')
        l._set_horz_foundations(x=max(dx, l.size.width + l.XM), y=l.YM,
                                ncols=f_cols, bases=bases)
        if 'xcards' in l._offset(playcards):
            dx = (max_width - ncols * l._get_stack_width(playcards)) / 2
        else:
            dx = l._halign(max_cols, ncols)
        dy = l.TEXT_HEIGHT if reserves and reserve_texts else 0
        l._set_rows(x=l.XM + dx, y=l.size.height + dy,
                    rows=rows, ncols=ncols, **l._offset(playcards))
        dx = l.XM if align == LEFT else l.size.width - l.XS
        dy = l.TEXT_HEIGHT if texts else 0
        l._set_horz_talon(x=dx, y=l.size.height + dy, texts=texts,
                          align=align, anchor='n', wastecards=wastecards)
        anchor = 'w' if align== RIGHT else'e'
        s['talon'].set_rounds(anchor='nnn' if l._has_waste and wastecards
                                        else anchor,
                           dx=l.XS * align if l._has_waste and not wastecards
                                           else 0)


class FanLayout(FreeCellLayout):
    """
    static block (top):
        - reserves. (horz. holdcards ignored. Ncards if reserve_texts.)
          foundations. (horz SUIT * 2. max of 10 cols.)
        - rows. (_offset if playcards.)

    dynamic block (bottom): align LEFT or RIGHT side. default LEFT.
        - talon (corner). waste (if Game._waste_. wastecards ignored).

    :cvar func _offset: dict('xcards': value)
    """

    _offset = lambda self, cards: {'xcards': cards}


class TowersLayout(layout.Layout):
    """
    static block (top):
        - reserves. (horz. holdcards ignored. Ncards if reserve_texts.)
          foundations. (horz SUIT * 2. max of 10 cols.)
        - rows. (_offset if playcards.)

    dynamic block (bottom): align LEFT or RIGHT side. default LEFT.
        - talon (corner). waste (if Game._waste_. wastecards ignored).

    :cvar func _offset: dict('ycards': value)
    """

    _offset = lambda self, cards: {'ycards': cards}
    _halign = lambda self, max_rows, piles: (max_rows - piles) * self.HXS

    def create(self, rows, ncols=None, playcards=18, bases=None,
               reserves=0, reserve_texts=False, texts=False, wastecards=0,
               align=LEFT, **kw):
        l, s = self, self.s
        assert l.size.width == 0
        ncols = ncols or rows
        # set foundation base caps
        bases = bases if type(bases) in (list, tuple) else l.SUITS
        max_cols = max(ncols, reserves + 4)
        center = lambda piles: l._halign(max_cols, piles)
        l._set_horz_reserves(x=l.XM + center(reserves), y=l.YM,
                             reserves=reserves, reserve_texts=reserve_texts,
                             anchor='s')
        dy = l.TEXT_HEIGHT if reserves and reserve_texts else 0
        l._set_rows(x=l.XM + center(ncols), y=l.size.height + dy, rows=rows,
                    ncols=ncols, **l._offset(playcards))
        l._set_horz_foundations(x=l.XM, y=l.YM, ncols=2, bases=bases[::2])
        l._set_horz_foundations(x=l.XM + l.size.width - 2 * l.XS, y=l.YM,
                                ncols=2, bases=bases[1::2])
        dx = l.XM if align == LEFT else l.size.width - l.XS
        dy = l.TEXT_HEIGHT if texts else 0
        l._set_horz_talon(x=dx, y=l.size.height + dy, texts=texts,
                          align=align, anchor='n', wastecards=wastecards)
        anchor = 'w' if align== RIGHT else'e'
        s['talon'].set_rounds(anchor='nnn' if l._has_waste and wastecards
                                        else anchor,
                           dx=l.XS * align if l._has_waste and not wastecards
                                           else 0)


class GloriaLayout(layout.Layout):
    """
    static block (top):
      - foundation. max 8 per N, no offset.
      - resereve. 1/2 NW, 1/2 NE, no offset ncards texts when reserve_texts.
      - row. S foundation, vert offset when playcards

    dynamic block (bottom): align LEFT or RIGHT side. default LEFT.
       - talon. SW | SE, no offset ncards texts when texts.
       - waste. E | W talon, horz offset when waste_cards. ncards texts when
         texts. Show when game has _waste_ that is not None.

    :cvar func _offset: dict('ycards': value)
    """
    _offset = lambda self, cards: {'ycards': cards}
    _halign = lambda self, max_rows, piles: (max_rows - piles) * self.HXS

    def create(self, rows, ncols=None, playcards=18, bases=None,
               reserves=2, reserve_texts=False, texts=False, wastecards=0,
               align=LEFT, **kw):
        l, s = self, self.s
        assert l.size.width == 0
        ncols = ncols or rows
        hres = reserves / 2
        # set foundation base caps
        bases = bases if type(bases) in (list, tuple) else l.SUITS
        f_cols = min(8, len(bases) / l.NDECKS)
        max_cols = max(ncols, reserves + f_cols)
        center = lambda piles: l._halign(max_cols, piles)
        l._set_horz_reserves(x=l.XM, y=l.YM, reserves=hres,
                             reserve_texts=reserve_texts, anchor='s')
        l._set_horz_foundations(x=l.XM + center(f_cols), y=l.YM, ncols=f_cols,
                                bases=bases)
        l._set_horz_reserves(x=l.XM + l.size.width - hres * l.XS, y=l.YM,
                             reserves=hres, reserve_texts=reserve_texts,
                             anchor='s')
        dy = l.TEXT_HEIGHT if reserves and reserve_texts else 0
        l._set_rows(x=l.XM + center(ncols), y=l.size.height + dy, rows=rows,
                    ncols=ncols, **l._offset(playcards))
        dx = l.XM if align == LEFT else l.size.width - l.XS
        dy = l.TEXT_HEIGHT if texts else 0
        l._set_horz_talon(x=dx, y=l.size.height + dy, texts=texts,
                          align=align, anchor='n', wastecards=wastecards)
        anchor = 'w' if align== RIGHT else'e'
        s['talon'].set_rounds(anchor='nnn' if l._has_waste and wastecards
                                        else anchor,
                           dx=l.XS * align if l._has_waste and not wastecards
                                           else 0)


class DoubleFivesLayout(FreeCellLayout):
    """
    - top: (reserves), foundations over many cols. Default 2 suit sets or 10
      suits.
    - below: rows
    - bottom: talon, waste, xwastes
    """

    def defaultAll(self):
        """
        defaultAll() -> None

        Set default for texts, groups, and regions.
        """
        game = self.game
        xwastes = self.s['xwastes']
        if game.s['xwastes'] and xwastes:
            if xwastes.ncards:
                self.set_ncards_text(game.s['xwastes'], **xwastes.ncards)
        super(DoubleFivesLayout, self).defaultAll(self)

    def create(self, xwastes, waste_align, xwastestext=False, **kw):
        super(DoubleFivesLayout, self).create(**kw)
        align = kw.get('align', LEFT)
        l, s, = self, self.s
        assert l._has_waste
        x, y = s['wastes'][-1].x, s['wastes'][-1].y
        waste = s['wastes'][-1]
        if align == LEFT:
            if waste_align == RIGHT:
                waste = l._create_stack(l.size.width - l.XS, y)
            else:
                x += l.XS
        else:
            if waste_align == LEFT:
                waste = l._create_stack(l.XM, y)
            else:
                x -= min(l.XM, l.XS * xwastes)
        waste._set_offset(0, 0)
        s['wastes'] = []
        for x in l.row_iter(x, xwastes):
            s['wastes'].append(self._create_stack(x, y))
            if xwastestext:
                s['wastes'][-1].set_ncards(anchor='n')
        s['wastes'].append(waste)  # waste is always last